package singleton

import (
	"fmt"
	"sync"
)

var lock = &sync.Mutex{}

type single struct {

}

var singleInstance *single

func GetInstance() *single {
	// 最开始时会有 nil 检查，
	// 确保 singleInstance 单例实例在最开始时为空。
	// 这是为了防止在每次调用 getInstance 方法时都去执行消耗巨大的锁定操作。
	// 如果检查不通过，则就意味着 singleInstance 字段已被填充。
	if singleInstance == nil {
		// singleInstance 结构体将在锁定期间创建。
		lock.Lock()
		defer lock.Unlock()

		// 在获取到锁后还会有另一个 nil 检查。
		// 这是为了确保即便是有多个协程绕过了第一次检查，
		// 也只能有一个可以创建单例实例。
		// 否则， 所有协程都会创建自己的单例结构体实例。
		if singleInstance == nil {
			fmt.Println("Creating single instance now.")
			singleInstance = &single{}
		} else {
			fmt.Println("Coroutine escape mutex lock. However, single instance already created.")
		}
	} else {
		fmt.Println("Single instance already created.")
	}

	return singleInstance
}
